/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2017-2020. All rights reserved.
 * Description:
 * Author: Huawei
 * Create: 2018-07-13
 */
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include "comm_knl_api.h"

MODULE_LICENSE("GPL");

#define COMM_DEV_CLASS "comm_dev_class"
#define COMM_DEV_NODE_NAME "comm_dev"
#define COMM_DEV_MAX_COUNT 1

#define DEV_PWM_NAME_KER "pwm"

void comm_cleanup_dev(CDEV_ST *pDev)
{
    dev_t dev_no;

    if ((pDev == NULL) || (pDev->dev_class == NULL))
        return;
    dev_no = MKDEV(pDev->dev_major, pDev->dev_minor);
    cdev_del(&pDev->cdev);
    device_destroy(pDev->dev_class, dev_no);
    class_destroy(pDev->dev_class);
    unregister_chrdev_region(dev_no, COMM_DEV_MAX_COUNT);

    return;
}
S32 comm_init_dev(CDEV_ST *pDev, struct file_operations *pfoprs)
{
    dev_t dev_no;
    int rc;
    struct device *dev = NULL;
#ifndef _PWM_UT_
    struct class *dev_class = NULL;
#else
    struct _class_ *dev_class = NULL;
#endif

    if ((pDev == NULL) || (pfoprs == NULL)) {
        pwm_err("comm_init_dev input para is NULL\n");
        return -EINVAL;
    }

    pDev->dev_class = NULL;

    rc = alloc_chrdev_region(&dev_no, 0, COMM_DEV_MAX_COUNT, DEV_PWM_NAME_KER);
    if (rc < 0) {
        pwm_err("alloc_chrdev_region for %s error: %d\n", DEV_PWM_NAME_KER, rc);
        return rc;
    }

    dev_class = class_create(THIS_MODULE, COMM_DEV_CLASS);
    if (IS_ERR(dev_class)) {
        pwm_err("class_create %s error\n", COMM_DEV_CLASS);
        rc = PTR_ERR(dev_class);
        goto exit_unregister_chrdev_region;
    }

    dev = device_create(dev_class, NULL, dev_no, NULL, DEV_PWM_NAME_KER);
    if (IS_ERR(dev)) {
        pwm_err("device_create %s error\n", DEV_PWM_NAME_KER);
        rc = PTR_ERR(dev);
        goto exit_class_destroy;
    }

    cdev_init(&pDev->cdev, pfoprs);
    pDev->cdev.owner = THIS_MODULE;
    rc = cdev_add(&pDev->cdev, dev_no, 1);
    if (rc) {
        pwm_err("cdev_add %s error\n", DEV_PWM_NAME_KER);
        goto exit_device_create;
    }

    pDev->dev_class = dev_class;
    pDev->dev_major = MAJOR(dev_no);
    pDev->dev_minor = MINOR(dev_no);

    return 0;

exit_device_create:
    device_destroy(dev_class, dev_no);
exit_class_destroy:
    class_destroy(dev_class);
exit_unregister_chrdev_region:
    unregister_chrdev_region(dev_no, COMM_DEV_MAX_COUNT);

    return rc;
}
